<?php
/**
 * Created by PhpStorm.
 * User: stupboy
 * Date: 2018/3/9
 * Time: 15:31
 * Mail:87658989@qq.com
 */

namespace app\api\logic;
use app\api\model;
use app\base\service\Redis;
use think\Db;
use think\Config;
use think\Exception;
use think\exception\DbException;
use think\Hook;
class Driver
{
    /**
     * 获取司机登入数据
     * @param $did
     * @return array
     */
    public function getLoginData($did){
        $defaultType = 0;
        $defaultCar  = 0;
        try{
            $field  = 'a.car_id,a.car_type_id,a.is_default,b.type,b.car_type,prop,c.number';
            $useCar = Db::name('driver_car_use')->alias('a')
                ->join('car c','a.car_id = c.car_id','left')
                ->join('car_type b ','c.car_type_id = b.car_type_id ','left')
                ->where('a.driver_id',$did)->field($field)->select();
        }catch (Exception $e){
            return [];
        }
        $data    = [];
        $types   = [];
        $carType = [];
        $prop    = [];
        $number  = [];
        foreach ($useCar as $v){
            $v['is_default']==1 && $defaultCar = $v['car_id'];
            $v['is_default']==1 && $defaultType = $v['car_type_id'];
            $v['is_default']==1 && $ret['default_car_type'] = $v['type'].'-'.$v['car_type'];
            $v['is_default']==1 && $ret['default_prop'] = $v['prop'];
            if($v['is_default']==1){
                $ret['car_number'] = $v['number'];
            }
            $data[$v['car_type_id']] = $v['car_id'];
            $carType[$v['type'].'-'.$v['car_type']] = $v['car_id'];
            $types[] = $v['car_type_id'];
            !empty($v['prop']) && $prop[$v['prop']]  = $v['car_id'];
            $number[$v['car_id']] = $v['number'];
        }
        $typeStr            = implode(',',$types);
        $ret['car_id']      = $defaultCar;
        $ret['car_type_id'] = $defaultType;
        $ret['cars']        = $typeStr;
        $ret['other_type']  = empty($data) ? null : $data;
        $ret['car_types']   = empty($carType) ? null : $carType;
        $ret['prop']        = empty($prop) ? null : $prop;
        $ret['numbers']     = empty($number) ? null : $number;
        return $ret;
    }

    /**
     * 司机接单/改派
     * @param $driver_id int 司机id
     * @param $oid int 订单id
     * @param $car_id int 车辆id
     * @param $state int 订单状态
     * @param $change int  是否改派
     * @param $is_admin boolean  是否后台派单
     * @return array
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function receiveOrder($driver_id=0,$oid=0,$car_id=0,$state = 4,$change=0, $is_admin = false)
    {
        $driver              = Db::name('driver')->find($driver_id);
        $car_id              = $car_id == 0 ? $driver['car_id'] : $car_id;
        $orderModel          = new model\Order();
        $order               = model\Order::get($oid);
        $planTime            = $order->ordergps ? $order->ordergps->plan_time : date('Y-m-d H:i:s');
        $useTime             = $order->orderfee ? $order->orderfee->pre_time : 3600;
        $isReorder           = $order->reorder;
        // 判断是否执行中订单
        $where['driver_id']  = $this->driverInfo['driver_id'];
        $where['order_state']= ['in','6,7,8'];
        $hasOrder            = $orderModel->where($where)->whereNull('delete_time')->select();
        // 司机状态必须是非下班状态 1是任务中 2是有预约单 3是听单中 4是下班
        if(!in_array($driver['work_state'],[1,2,3]) && !$is_admin){
            return [0,138];
        }
        // 司机在执行任务时非续单模式则派单失败
        if($driver['work_state']==1 && $isReorder==0 && $is_admin==false){
            return [0,139];
        }
        // 非续单且没有其他在执行订单
        if(!empty($hasOrder) && $isReorder==0){
            return [0,121];
        }
        // 车辆是否有在执行订单
        $carWhere['car_id'] = $car_id;
        $carWhere['order_state'] = ['in', '6,7,8'];
        $carHasOrder = $orderModel->where($carWhere)->whereNull('delete_time')->select();
        // 相同订单可忽略
        if (count($carHasOrder) > 1 || (!empty($carHasOrder) && $isReorder==0 && (int)$oid !== $carHasOrder[0]['order_id'])) {
            if($is_admin==false) return [0, 147];
        }
        // 判断车是否归属服务公司 自有用车派自有车辆
        $carInfo = Db::name('car')->alias('a')
            ->join('company b' , 'a.company_id = b.company_id' ,'left')
            ->join('company c' , 'a.entrust_company_id = c.company_id' , 'left')
            ->field('a.*,b.company_mode,c.company_mode entrust_company_mode')
            ->where('a.car_id',$car_id)
            ->find();
        if($order->pay_type == 4 ){
            if( $carInfo['entrust_company_id'] > 0 ){
                return [0,141];
            }
        }else{
            if( $carInfo['company_mode'] != 2 && $carInfo['entrust_company_mode'] != 2){
                return [0,142];
            }
        }
        // 取出司机全部已派单订单
        $driverOrders = Db::name('order')->alias('a')
            ->join('order_gps b','a.order_id = b.order_id','left')
            ->join('order_fee c','a.order_id = c.order_id','left')
            ->where('a.driver_id',$driver_id)
            ->where('a.order_state','in','5,6,7,8')
            ->whereNull('a.delete_time')
            ->field('a.order_id,b.plan_time,c.pre_time')
            //->order('b.plan_time')
            ->select();
        // 派单间隔时间
        $limitDispatchTime = Config::get('pre_limit');
        if(!empty($driverOrders)){
            foreach ($driverOrders as $driverOrder){
                $dispatchTyp = strtotime($planTime) < strtotime($driverOrder['plan_time']) ? true : false;
                if($dispatchTyp){
                    // 待派订单的预计出发时间 + 预计耗时 + 派单间隔时间 大于 司机已派单计划出行时间 则提示错误
                    if(strtotime($planTime) + $useTime + $limitDispatchTime > strtotime($driverOrder['plan_time'])){
                        return [0,122];
                    }
                }else{
                    // 司机已派单预计出发时间 + 预计耗时 + 派单间隔时间 大于 待派单预计出发时间 则提示错误
                    if(strtotime($driverOrder['plan_time']) + intval($driverOrder['pre_time']) + $limitDispatchTime > strtotime($planTime)){
                        return [0,122];
                    }
                }
            }
        }
        $Info                = model\Driver::get($driver_id);
        $carInfo             = $Info->car;
        $carInfoNew          = Db::name('car')->where('car_id',$car_id)->find();
        $data                = [
            'driver_id'   => $driver_id,
            'car_id'      => $car_id > 0 ? $car_id : $carInfo->car_id,
            'dispatch_car_type_id' => $car_id > 0 ? $carInfoNew['car_type_id'] : $carInfo->car_type_id,
            'order_state' => 5,
            'orders_time' => date('Y-m-d H:i:s'),
            'car_number'  => $car_id > 0 ? $carInfoNew['number'] : $carInfo->number];
        // 派单数据写入
        $ret = (new model\Order())->save($data, ['order_id' => $oid,'order_state'=> ['IN', [1,2,4,5,6,7,8]]]);
        // 接单失败
        if ($ret < 1) {
            return [0,404];
        } else {
            // 增加派单记录
            (new \app\api\logic\Order())->addDispatchLog($oid,$data['driver_id'],$data['car_id']);

            if($change==0){
                // 非改派，接单模式
                Hook::listen('rece_order',$oid);
            }else{
                // 改派逻辑
                (new model\Driver())->save(['work_state'=>3,'task_time'=>0],['driver_id'=>$order->driver_id]);
                $param['oid']       = $oid;
                $param['driver_id'] = $order->driver_id;
                $param['pid']       = $order->passenger_id;
                $param['newPid']    = $driver_id;
                Hook::listen('change_dispatch',$param);
            }

            // 司机状态修改
            (new model\Driver())->save(['work_state'=>2,'task_time'=>$planTime],['driver_id'=>$driver_id]);
        }
        return [1,'ok'];
    }

    /**
     * 司机取消订单
     * @param int $driver_id
     * @param int $oid
     * @return array
     */
    public function cancelOrder($driver_id=0,$oid=0){
        $order                  = new model\Order();
        $where['a.order_state'] = ['in','5,6,7'];
        $where['a.order_id']    = $oid;
        $info = $order->alias('a')
            ->join('order_gps b','a.order_id = b.order_id','left')
            ->field('a.driver_id,b.go_time')
            ->where($where)->find();
        if($info['driver_id']!=$driver_id){
            return [0,404];
        }
        if(!empty($info['go_time'])){
            return [0,126];
        }
        $data                = [
            'driver_id'   => null,
            'orders_time' => null,
            'car_id'      => 0,
            'order_state' => 4,
            'car_number'  => null
        ];
        $order->save($data,['order_id'=>$oid]);
        (new model\Driver())->save(['work_state'=>3],['driver_id'=>$driver_id]);
        Hook::listen('cancel_order_driver',$oid);
        return [1,'ok'];
    }

    public function getLearDrivers($oid){
        try{
            $order       = Db::name('order')->alias('a')
                ->join('car_type b','a.car_type_id = b.car_type_id','left')
                ->join('order_gps c','a.order_id = c.order_id','left')
                ->where('a.order_id',$oid)
                ->field('a.order_id,from_lon,from_lat,b.type,b.car_type,a.passenger_id')
                ->find();
        }catch (DbException $e){
            $order = [];
        }
        $where['passenger_id'] = $order['passenger_id'];
        $where['order_state']  = ['in','9,10,11'];
        $historyOrder  = Db::name('order')->where($where)->field('driver_id,car_id')->order('order_id desc')->find();
        $historyDriver = $historyOrder['driver_id'];
        $historyCar    = isset($historyOrder['car_id']) ? $historyOrder['car_id'] : 0;
        if(empty($order)) return [];
        $type    = '2,3';
        $allType = [
            2=>[2,3,4,9],// 优选 升 舒适 豪华 商务
            3=>[3,4,9],// 舒适 升 豪华 商务
            4=>[4,9],// 豪华 升 商务
            9=>[9]
        ];
        $carType = $allType[$order['car_type']];//$order['car_type']
        // 4办司机
        try{
            $officeDrivers = Db::name('driver_car_use')->alias('a')
                ->join('car b','a.car_id=b.car_id','left')
                ->join('car_type c','b.car_type_id = c.car_type_id','left')
                ->where('b.prop',4)
                ->where('c.type','in',$type)
                ->where('c.car_type','in',$carType)
                ->field("a.driver_id,a.car_id,b.number,c.type,c.car_type,case when a.car_id = $historyCar then 1 else 0 end defaultCar")
                ->select();
        }catch (DbException $e){
            $officeDrivers = [];
        }
        if(empty($officeDrivers)) return [];
        $newDrivers = [];
        foreach ($officeDrivers as $officeDriver){
            $newDrivers[$officeDriver['driver_id']]['cars'][] = $officeDriver;
        }
        $redis       = Redis::getInstance();
        $arr         = $redis->hScanYield('car.driver.4.login','*');
        $backDriver  = [];
        $nowTime     = time();
        foreach ($arr as $v){
            $driver    = unserialize($v);
            $driverId  = $driver['driver_id'];
            $workState = $driver['work_state'];
            $note      = [3=>'空闲',2=>'接单中',1=>'接单中',4=>'下班'];
            // 必须是听单状态
            // if(!in_array($driver['work_state'],[2,3])) continue;
            // id 必须大于0
            if($driver['user_id']==0) continue;
            // GPS定位时间不超过5分钟
            if($nowTime - $driver['gps_time']/1000>60){
                $workState = 4;
            }
            if(isset($newDrivers[$driverId])){
                $newDrivers[$driverId]['name']     = $driver['name'];
                $newDrivers[$driverId]['driver_id']= $driver['driver_id'];
                $newDrivers[$driverId]['distance'] = round(getGpsDistance($order['from_lon'],$order['from_lat'],$driver['lon'],$driver['lat']),1);
                $newDrivers[$driverId]['defaultDriver']  = $historyDriver == $driverId ? 1 : 0;
                // 1：执行任务中，2：有预约订单，3：听单中，4：下
                $newDrivers[$driverId]['note']     = $note[$workState];
                $newDrivers[$driverId]['state']    = $workState;
                $backDriver[] = $newDrivers[$driverId];
            }
        }
        // 根据距离排升序
        // array_multisort($distanceArr,SORT_ASC,SORT_NUMERIC,$drivers);
        return $backDriver;
    }
}